iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
0

前言:架構對於初學者來說,非常重要,但是非常難學,當初我在學習時,雖然網路上有很多文章,但每一個都不知道再供三小。即便我這篇文章,或許你也會聽不懂、看不懂。但別放棄,架構真的太、太、太重要!!一定要至少想辦法學會 MVP,再前往 MVVM

Android app 的【架構】目前分為 MVC MVP MVVM

  • 推薦指數 MVVM > MVP > MVC
  • 困難指數 MVVM > MVP > MVC

Q:架構是什麼?

A:該架構指的就是 程式碼 的 架構

  • 可以理解成 => 達到同樣畫面效果的同時,我們的程式碼要整理成什麼樣子?

我們拿昨天最後的程式碼和畫面為例

Yes

我們把所有【畫面顯示】【判斷句】【邏輯】甚至【資料庫請求】等等都寫在 onCreate 裡面,未來程式碼幾千行的時候,會導致你自己都看不懂自己在寫什麼?

即使看得懂,其他人來維護的時候,也會傻眼。

但是當你告訴別人:我這個專案是以 MVP 架構來寫的,人家至少心裡就有個底知道你的排版大概長什麼樣子。


MVP 就是下列三個單字的縮寫

各自負責不同的程式碼

拿昨天帳號密碼的例子來解釋,想法上應該是

  • View 偵測到有人按下登入按鈕

  • 請 Presenter 判斷一下帳號密碼是否正確

  • 若正確 -> 請 View 顯示成功

  • 若錯誤 -> 請 View 顯示失敗

View 的工作:Presenter 要我顯示什麼,我就顯示什麼,但我可以決定要用 TextView 顯示,還是用 Toast( 吐司 ) 顯示。 (只負責畫面)

Presenter 的工作:View 會丟給我帳號密碼,我比對帳號是否為 1234,密碼是否為 5678,接著叫 View 顯示成功或失敗。我並不知道他是用 TextView 顯示,還是用 Toast( 吐司 )顯示。 (只負責邏輯:運算、判斷)

大概了解之後 我們看一下程式碼是怎麼完成這些分工的!

我們必須要有 View 跟 Presenter

  • View 就是 MainActivity
  • Presenter 需要自己創

創一個 Class 名叫 Presenter

class Presenter {

}

創一個 fun 並傳進 account 和 password

class Presenter {

    fun compare(account: String, password: String) {
        
    }

}

比較帳號密碼是否是我們要的

class Presenter {

    fun compare(account: String, password: String) {
        if (account == "1234" && password == "5678") {
            // Todo 需要通知 MainActivity 顯示成功
        } else {
            // Todo 需要通知 MainActivity 顯示成功
        }
    }

}

Q:要怎麼通知 MainActivity 呢?

A:只好在 View 創造 Presenter 物件的時候,把自己丟進去

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 創一個 Preseneter 物件並丟進自己(this)
    val presenter = Presenter(this) 

}
class Presenter(val view: MainActivity) { // 取得 MainActivity 物件

    fun compare(account: String, password: String) {
        if (account == "1234" && password == "5678") {
            // Todo 需要通知 MainActivity 顯示成功
        } else {
            // Todo 需要通知 MainActivity 顯示成功
        }
    }

}

這樣 Presenter 也拿到 View 的物件

但是我們還沒有寫要如何顯示成功失敗,讓我們先在 View 寫兩個 function

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val presenter = Presenter(this)

}

fun showSuccess(){
    Toast.makeText(this,"登入成功",Toast.LENGTH_SHORT).show()
}

fun showFailure(){
    Toast.makeText(this,"登入失敗",Toast.LENGTH_SHORT).show()
}

這樣 Presenter 也知道要呼叫 View 的什麼方法了!

class Presenter(val view: MainActivity) {

    fun compare(account: String, password: String) {
        if (account == "1234" && password == "5678") {
            view.showSuccess() // 請 View 顯示成功
        } else {
            view.showFailure() // 請 View 顯示失敗
        }
    }

}

最後就是一開始要將用戶輸入的 帳號、密碼,交給 Presenter 處理

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val presenter = Presenter(this)

    btn_login.setOnClickListener { // 按下 login
        val account = et_account.text.toString()
        val password = et_password.text.toString()

        // 將 EditText 裡的帳號密碼交給 Presenter
        presenter.compare(account, password) 

    }

    btn_reset.setOnClickListener {
        et_account.text.clear()
        et_password.text.clear()
    }

}

fun showSuccess() {
    Toast.makeText(this, "登入成功", Toast.LENGTH_SHORT).show()
}

fun showFailure() {
    Toast.makeText(this, "登入失敗", Toast.LENGTH_SHORT).show()
}

最後大概是這樣的邏輯

Yes

【其實上述的例子不是真正的 MVP 架構,但是精神已經有到。】

其實最讓新手學習困難的點是,View 和 Presenter 到底是怎麼溝通的?

不同點:真正的 MVP 架構,Presenter 裡面並不會像我們直接取得 MainActivity 物件的做法,而是利用一個介面( interface ) 做為兩者溝通的橋梁

不完整點:我們還沒有使用到 Model,這部分我們之後會談到。


上一篇
Day8 - Android App 動態改變元件屬性
下一篇
Day10 - Android App 的 MVP 架構 (2/2)
系列文
菜雞 Android APP 從安裝 Android Studio 到上架 Google Play30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言